using System;
using System.Data;
using System.Text;

namespace DataServices
{
	/// <summary>
	/// Summary description for DataException.
	/// </summary>
	public class DataException : ApplicationException
	{
		public enum DataExceptionCode
		{
			Concurrency,
			ConnectionFailure,
			DatabaseFailure,
			LoginFailure,
			Constraint,
			Transaction,
			Locks,
			General
		}

		private DataExceptionCode exceptionCode = DataExceptionCode.General;
		private DataSet ds;
		private DataRow[] drs = new DataRow[0];
		private StringBuilder log = new StringBuilder();

		public delegate void ProcessExceptionHandler(ref Exception ex, ref StringBuilder log, ref DataExceptionCode exCode);

		public DataException(string message, Exception ex, DataSet ds, ProcessExceptionHandler peh) : base(message,ex)
		{
			this.ds = ds;

			if (ex.GetType() == typeof(ConstraintException))
			{
				log.Append("ConstraintException occured \r\n");
				exceptionCode = DataExceptionCode.Constraint;
			}
			else if (ex.GetType() == typeof(DBConcurrencyException))
			{
				log.Append("DBConcurrencyException occured \r\n");
				exceptionCode = DataExceptionCode.Concurrency;
			}
			else 
			{
				log.Append("DataProvider Exception occurred \r\n");
				peh(ref ex, ref log, ref exceptionCode);
			}
	
			DetectRowErrors(ds);

			log.Append("Original Exception: \r\n");
			log.Append(ex.ToString());
			
			LogException(log.ToString());

		}

		public void DetectRowErrors(DataSet dsError)
		{
			if (dsError!=null)
			{
				if (dsError.HasErrors)
				{
					log.Append("************************** \r\n");
					log.Append("Errors Detected in DataSet: \r\n\r\n");
					foreach (DataTable dt in dsError.Tables)
					{
						if (dt.HasErrors)
						{
							drs = dt.GetErrors();
							log.Append("Entity: " + dt.TableName + "\r\n");
							foreach (DataRow dr in dt.Rows)
							{
								if (dr.HasErrors)
								{
									log.Append("\t Key: " +  dr[dt.PrimaryKey[0]] + "\r\n");
									log.Append("\t " + dr.RowError + " \r\n");
									log.Append("\r\n");

									foreach (DataColumn dc in dr.GetColumnsInError())
									{
										log.Append("\t\t ColumnName: " + dc.ColumnName + "\r\n");
										log.Append("\t\t Error: " + dr.GetColumnError(dc) + "\r\n");
										log.Append("\r\n");
									}
								}
							}
						}
					}
				}
			}
		}

		public void LogException(string logMessage)
		{
			
		}

		public DataExceptionCode ExceptionCode
		{
			get
			{
				return exceptionCode;
			}
		}

		public DataSet OriginalDataSet
		{
			get
			{
				return ds;
			}
		}

		public DataRow[] RowsWithErrors
		{
			get
			{
				return drs;
			}
		}
	}
}
